package uha.ensisa.jordanVoegtlin.chart;

import java.awt.Color;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.io.File;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

import javax.swing.JFrame;
import javax.swing.JPanel;
import org.jfree.chart.plot.XYPlot;
import org.jfree.chart.ChartFactory;
import org.jfree.chart.ChartPanel;
import org.jfree.chart.ChartUtilities;
import org.jfree.chart.JFreeChart;
import org.jfree.chart.plot.PiePlot;
import org.jfree.chart.plot.PiePlot3D;
import org.jfree.chart.plot.PlotOrientation;
import org.jfree.chart.renderer.category.AbstractCategoryItemRenderer;
import org.jfree.chart.renderer.category.BarRenderer;
import org.jfree.data.category.CategoryDataset;
import org.jfree.data.category.DefaultCategoryDataset;
import org.jfree.data.general.Dataset;
import org.jfree.data.general.DefaultPieDataset;
import org.jfree.data.general.PieDataset;
import org.jfree.data.xy.OHLCDataset;
import org.jfree.data.xy.XYDataset;
import org.jfree.data.xy.XYSeries;
import org.jfree.data.xy.XYSeriesCollection;

public class Chart {

	private ChartType type;
	private JFreeChart chart;
	private Dataset dataset;
	private Dimension dimension = new Dimension(500, 300);
	private String title = "title";
	private String xAxisLabel = "xAxisLabel";
	private String yAxisLabel = "yAxisLabel";
	private PlotOrientation orientation = PlotOrientation.VERTICAL;
	private String fileName;
	private List<Color> colors = new ArrayList<Color>();
	private AbstractCategoryItemRenderer renderer = new BarRenderer();

	public void setDimension(int w, int h) {
		this.dimension = new Dimension(w, h);
		System.out.println("dimension : " + dimension);
	}

	public void setTitle(String title) {
		this.title = title;
		System.out.println("title : " + title);
	}

	public void setxAxisLabel(String xAxisLabel) {
		this.xAxisLabel = xAxisLabel;
		System.out.println("xAxisLabel : " + xAxisLabel);
	}

	public void setyAxisLabel(String yAxisLabel) {
		this.yAxisLabel = yAxisLabel;
		System.out.println("yAxisLabel : " + yAxisLabel);
	}
	public void setAxisLabel(String xAxisLabel, String yAxisLabel)
	{
		setxAxisLabel(xAxisLabel);
		setyAxisLabel(yAxisLabel);
	}
	public void setOrientation(String orientation) {
		if (orientation.equalsIgnoreCase("vertical"))
			this.orientation = PlotOrientation.VERTICAL;
		else
			this.orientation = PlotOrientation.HORIZONTAL;
	}

	public void setOrientation(PlotOrientation orientation) {
		this.orientation = orientation;
		System.out.println("orientation : " + orientation);
	}

	public void setFileName(String fileName) {
		this.fileName = fileName;
		System.out.println("fileName : " + fileName);
	}

	public void setType(String type) {
		if (type.equalsIgnoreCase("XYLine")) {
			this.type = ChartType.XYLine;
			return;
		}
		if (type.equalsIgnoreCase("Bar")) {
			this.type = ChartType.Bar;
			return;
		}
		if (type.equalsIgnoreCase("Pie")) {
			this.type = ChartType.Pie;
			return;
		}
		if (type.equalsIgnoreCase("Pie3D")) {
			this.type = ChartType.Pie3D;
			return;
		}
	}

	public JFreeChart getChart() {
		if (type == ChartType.XYLine) {
			this.chart = ChartFactory.createXYLineChart(title,
					xAxisLabel, yAxisLabel, (XYDataset) dataset, orientation,
					false, true, false);
			int i=0;
			for(Color c : colors)
				((XYPlot)this.chart.getPlot()).getRenderer().setSeriesPaint(i++, c);
			return  this.chart;
		}
		if (type == ChartType.Bar) {
			this.chart = ChartFactory.createBarChart(title, xAxisLabel,
					yAxisLabel, (CategoryDataset) dataset,
					PlotOrientation.VERTICAL, true, true, false);
			this.chart.getCategoryPlot().setRenderer(renderer);
			return  this.chart;
		}
		if (type == ChartType.Pie) {
			this.chart = ChartFactory.createPieChart(title,
					(PieDataset) dataset, true, true, false);
			int i=0;
			for(Color c : colors)
				((PiePlot) this.chart.getPlot()).setSectionPaint(i++, c);
			return  this.chart;
		}
		if (type == ChartType.Pie3D) {
			this.chart = ChartFactory.createPieChart3D(title,
					(PieDataset) dataset, true, true, false);
			PiePlot3D plot = (PiePlot3D) chart.getPlot();
	        plot.setStartAngle(90);
			int i=0;
			for(Color c : colors)
				((PiePlot) this.chart.getPlot()).setSectionPaint(i++, c);
			return  this.chart;
		}
		if (type == ChartType.HighLow) {
			this.chart = ChartFactory.createHighLowChart(title, xAxisLabel, yAxisLabel, (OHLCDataset) dataset, false);
			return this.chart;
		}
		return null;
	}

	public void addData(List list) {
		System.out.println("addData : " + list);
		if (type == ChartType.XYLine) {
			dataset = new XYSeriesCollection();
			for (Object object : list) {
				XYSeries series = new XYSeries(title);
				
				System.out.println("Series : " + object);
				Iterator serieIt=((List) object).iterator();
				while(serieIt.hasNext())
				{
					Object serieObject = serieIt.next();
					if(serieObject instanceof String)
					{
						changeColor(0, parse((String) serieObject));
					}
					else
						if(serieObject instanceof List)
						{
							List data=(List) serieObject;
							double x = (Double) data.get(0);
							double y = (Double) data.get(1);
							series.add(x, y);
							((XYSeriesCollection) dataset).addSeries(series);
						}
					}
			}
			return;
		}
		if (type == ChartType.Pie || type == ChartType.Pie3D) {
			dataset = new DefaultPieDataset();
			for (Object object : list)
			{
				if(object instanceof Integer)
					((DefaultPieDataset) dataset).setValue(object.toString(),
						(Number) object);
				int i = 0;
				if(object instanceof List)
				{
					List l = (List) object;
					((DefaultPieDataset) dataset).setValue((Comparable) l.get(0),(Number)l.get(1));
					if(((List) object).size()>=3)
						changeColor(i,parse(((List) object).get(2).toString()));
					i++;
				}
			}
			return;
		}
		if (type == ChartType.Bar) {
			dataset = new DefaultCategoryDataset();
			int i = 0;
			for (Object object : list) {
				((DefaultCategoryDataset) dataset).addValue(
						(Number) ((List) object).get(0), ((List) object).get(1)
								.toString(), ((List) object).get(2).toString());
				if(((List) object).size()>=4)
					changeColor(i,parse(((List) object).get(3).toString()));
				i++;
			}
			return;
		}
	}

	public Color parse(String nm) throws NumberFormatException {
		if(nm.equalsIgnoreCase("white"))
			return Color.white;
		if(nm.equalsIgnoreCase("black"))
			return Color.black;
		if(nm.equalsIgnoreCase("green"))
			return Color.green;
		if(nm.equalsIgnoreCase("red"))
			return Color.red;
		if(nm.equalsIgnoreCase("blue"))
			return Color.blue;
		if(nm.equalsIgnoreCase("yellow"))
			return Color.yellow;
		if(nm.equalsIgnoreCase("pink"))
			return Color.pink;
		if (nm.startsWith("#")) {
			nm = nm.substring(1);
		}
		nm = nm.toLowerCase();
		if (nm.length() > 6) {
			throw new NumberFormatException(
					"nm is not a 24 bit representation of the color, string too long");
		}
		Color color = new Color(Integer.parseInt(nm, 16));
		return color;
	}

	public void changeColor(int index, Color color) {
		renderer.setSeriesPaint(index, color);
		colors.add(color);
	}

	public void Display() {
		final JFrame frame = new JFrame(title);
		JPanel panel = new JPanel();
		frame.getContentPane().add(panel);

		panel.add(new ChartPanel(getChart()));
		frame.pack();

		EventQueue.invokeLater(new Runnable() {
			public void run() {
				frame.setVisible(true);
			}
		});
	}

	public void Save(String fileType) {
		if (fileType.equalsIgnoreCase("png"))
			try {
				ChartUtilities.saveChartAsPNG(new File(fileName), getChart(),
						dimension.width, dimension.height);
				System.out.println("Save in png");
			} catch (Exception e) {
				e.printStackTrace();
			}
		else
			try {
				ChartUtilities.saveChartAsPNG(new File(fileName), getChart(),
						dimension.width, dimension.height);
				System.out.println("Save in jpg");
			} catch (Exception e) {
				e.printStackTrace();
			}
	}

}
